﻿using com.nm.Hook;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace com.nm
{
    public sealed class HookService
    {
        private HookService()
        {
            var assemblys = AppDomain.CurrentDomain.GetAssemblies().Where(item => item.GlobalAssemblyCache == false);
            foreach (var k in assemblys)
            {
                FindAndRegister(k);
            }
        }

        private void FindAndRegister(System.Reflection.Assembly assembly)
        {
            var type = typeof(BaseHook);
            try
            {
                var modules = assembly.GetTypes().Where(item => item.BaseType == type || item.IsSubclassOf(type));
                foreach (var k in modules)
                {
                    Register(k);
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                Log.Error("加载Type错误：{0}\n详细信息：{1}", "ReflectionTypeLoadException", ex.Message, ex.ToString());
            }
            catch (Exception ex)
            {
                Log.Error("注册错误：{0}\n详细信息：{1}", "Exception", ex.Message, ex.ToString());
            }
        }

        private void Register(Type pHander)
        {
            var t = pHander;
            while (t != null && t.BaseType != typeof(BaseHook))
            {
                t = t.BaseType;
            }
            if (t == null) return;
            if (_hooks == null) _hooks = new Dictionary<int, IList<IHook>>();
            var inc = Activator.CreateInstance(pHander) as BaseHook;
            if (inc == null) return;
            var list = _hooks.Where(item => item.Key == inc.HookType).Select(item => item.Value).FirstOrDefault() ??
                       new List<IHook>();
            list.Add(inc);
            _hooks[inc.HookType] = list.OrderByDescending(item => item.Priority).ToList();
        }

        private static HookService _instance;

        public static HookService Instance
        {
            get { return _instance ?? (_instance = new HookService()); }
        }

        private Dictionary<int, IList<IHook>> _hooks;

        public void Invoke(HookTypes pHookEvent, params object[] pArgs)
        {
            Invoke((int)pHookEvent, pArgs);
        }

        public void Invoke(int pHookEvent, params object[] pArgs)
        {
            if (!_hooks.ContainsKey(pHookEvent)) return;
            var list = _hooks[pHookEvent];
            var qs = list.OrderByDescending(item => item.Priority);
            foreach (var k in qs)
            {
                bool isEnd;
                var r = k.Execute(out isEnd, pArgs);
                Log.WriteLog("执行：{0} 结果： {1}", "HOOK Execute", Log.LogType.INFO, k, r);
                if (isEnd) break;
            }
        }
    }
}